package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MemberSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

//
@Aspect
@Component
public class AutoFillAspect {
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void AutoFillPT(){}

    @Before("AutoFillPT()")
    public void autoFill(JoinPoint joinPoint) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        /**
         * 获取注解参数
         */
        //1.获取方法签名(使用methodSingature获取等多的方法)
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //2.获取插入点方法上的AutoFill注解
        AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);
        //3.获取注解的value值
        OperationType value = annotation.value();

        /**
         * 获得形参
         */
        //1.获得方法的形参(将所有的形参存储到数组中)
        Object[] args = joinPoint.getArgs();
        //2.拿到形参（因为我们方法上都分装好了所以就一个形参就是 员工对象）
        Object arg = args[0];

        /**
         * 获取创建时间、更新时间、创建人、更新人
         */
        LocalDateTime createTime = LocalDateTime.now();
        LocalDateTime updateTime = LocalDateTime.now();
        Long createUser = BaseContext.getCurrentId();//获取当前登录用户的id id值存放到现成的存储空间中
        Long updateUser = BaseContext.getCurrentId();

        /**
         * 判断value的值，为INSERT，UPDATE则填充创建时间、更新时间、创建人、更新人
         */
        if (value == OperationType.INSERT){
            //1.拿到所需要的方法通过 反射！！！
            Method setCreateTime = arg.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class);
            Method setUpdateTime = arg.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
            Method setCreateUser = arg.getClass().getDeclaredMethod("setCreateUser", Long.class);
            Method setUpdateUser = arg.getClass().getDeclaredMethod("setUpdateUser", Long.class);

            //2.调用方法填充数据
            setCreateTime.invoke(arg, createTime);
            setUpdateTime.invoke(arg, updateTime);
            setCreateUser.invoke(arg, createUser);
            setUpdateUser.invoke(arg, updateUser);
        } else if (value == OperationType.UPDATE) {
            //3.重复if的操作
            Method setUpdateTime = arg.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
            Method setUpdateUser = arg.getClass().getDeclaredMethod("setUpdateUser", Long.class);
            setUpdateTime.invoke(arg, updateTime);
            setUpdateUser.invoke(arg, updateUser);
        }

    }

}